<?php
/**
 * Database test case
 *
 * Encapsulate reusable code for DB testing, providing methods to compare
 * DB results with expected data stored in XML files.
 *
 * Patrick Ogay Zend-DB-MAPPER-TESTS
 * analog
 *   http://techportal.ibuildings.com/2010/12/07/unit-testing-databases-with-zend-framework/
 *   https://github.com/ibuildings/zf-db-testing
 *   author: Devis Lucato <devis@ibuildings.com>  copyright: Ibuildings UK
 */

require_once 'PHPUnit/Extensions/Database/DataSet/DefaultDataSet.php';
require_once 'PHPUnit/Extensions/Database/DataSet/DataSetFilter.php';

abstract class DatabaseTestCaseAbstract extends Zend_Test_PHPUnit_DatabaseTestCase {
	const DEFAULT_CONNECTION_SCHEMA = 'main';

	/**
	 * Variable to be defined in each test case
	 *
	 * @var string
	 */
	protected $_initialSeedFile = '';

	/**
	 * Allow to override the global configuration for a particular test case
	 *
	 * @var string
	 */
	protected $_seedFilesPath = NULL;

	/**
	 * Parameter for Zend_Test_PHPUnit_Db_Connection
	 *
	 * @var string
	 */
	protected $_connectionSchema = self::DEFAULT_CONNECTION_SCHEMA;

	/**
	 * Connection to testing database
	 *
	 * @var Zend_Test_PHPUnit_Db_Connection
	 */
	protected $_connectionMock;

	/**
	 * Application configuration
	 *
	 * @var Zend_Config_Ini
	 */
	private $__configuration = NULL;

	/**
	 *  phpunit-Setup
	 */
	public function setUp() {
		parent::setUp();
		// $this->testExcludeFilteredBlog();
		$this->_bootstrap = new Zend_Application('testing', APPLICATION_PATH . '/configs/application.ini');
	}

	/**
	 * Filter ->http://www.phpunit.de/manual/3.5/en/phpunit-book.html
	 * @param Zend_Test_PHPUnit_Db_DataSet_QueryDataSet $dataSet
	 * @param string                                    $excluded
	 * @return PHPUnit_Extensions_Database_DataSet_DataSetFilter
	 */
	public function excludeField($dataSet, $excluded) {
		$tableNames = array('blog');
		//$dataSet = $this->getConnection()->createDataSet();

		$filterDataSet = new PHPUnit_Extensions_Database_DataSet_DataSetFilter($dataSet);
		$filterDataSet->setExcludeColumnsForTable('blog', array($excluded));
		return $filterDataSet;
	}

	/**
	 * Returns the application configuration
	 *
	 * @return Zend_Config_Ini
	 */
	public function getConfiguration() {
		if ($this->__configuration == NULL) {
			$this->__configuration = new Zend_Config_Ini(APPLICATION_PATH . '/configs/tests.ini');
		}

		return $this->__configuration;
	}

	/**
	 * Returns the seed files folder path
	 *
	 * @return string
	 */
	public function getSeedFilesPath() {
		if ($this->_seedFilesPath == NULL) {
			$this->_seedFilesPath = $this->getConfiguration()->tests->seeds->folder;
		}

		return rtrim($this->_seedFilesPath, '/') . '/';
	}

	/**
	 * Returns the test database connection.
	 *
	 * @return PHPUnit_Extensions_Database_DB_IDatabaseConnection
	 */
	protected function getConnection() {
		if ($this->_connectionMock == NULL) {
			$dbAdapterName = $this->getConfiguration()->tests->dbadapter;
			$dbAdapterParams = $this->getConfiguration()->tests->dbparams->toArray();

			$connection = Zend_Db::factory($dbAdapterName, $dbAdapterParams);

			$this->_connectionMock = $this->createZendDbConnection($connection, $this->_connectionSchema);

			Zend_Db_Table_Abstract::setDefaultAdapter($connection);
		}
		return $this->_connectionMock;
	}

	/**
	 * Retrieve from flat XML files data used to populate the database
	 *
	 * @return PHPUnit_Extensions_Database_DataSet_IDataSet
	 */
	protected function getDataSet() {
		return $this->createFlatXmlDataSet($this->getSeedFilesPath() . $this->_initialSeedFile);
	}

	/**
	 * Convert a Rowset to a Dataset
	 *
	 * @param  Zend_Db_Table_Rowset_Abstract $rowset
	 * @param  string                        $tableName
	 * @return PHPUnit_Extensions_Database_DataSet_DefaultDataSet
	 */
	public function convertRowsetToDataSet($rowset, $tableName = NULL) {
		$rowsetDataSet = new Zend_Test_PHPUnit_Db_DataSet_DbRowset($rowset, $tableName);
		return new PHPUnit_Extensions_Database_DataSet_DefaultDataSet(array($rowsetDataSet));
	}

	/**
	 * Convert a Record to a Dataset
	 *
	 * @param  array  $data
	 * @param  string $tableName
	 * @return PHPUnit_Extensions_Database_DataSet_DefaultDataSet
	 */
	public function convertRecordToDataSet(Array $data, $tableName) {
		$rowset = new Zend_Db_Table_Rowset(array('data' => array($data)));
		return $this->convertRowsetToDataSet($rowset, $tableName);
	}

	/**
	 * @param array $blogAr
	 * @param       $tableName
	 * @return PHPUnit_Extensions_Database_DataSet_DefaultDataSet
	 *
	 * array von Application_Model_Blog
	 */
	public function convertModelArrayToDataSet(Array $blogAr, $tableName) {
		// in Array von Models in "normales" Array convertieren
		$i = 0;
		$data = array();
		foreach ($blogAr as $blogmodel) {
			$data[$i] = $blogmodel->toArray();
			$i++;
		}
		// $data1 = $data[0]; /* erstes element */
		$rowset = new Zend_Db_Table_Rowset(array('data' => $data));
		return $this->convertRowsetToDataSet($rowset, $tableName);
	}

	/**
	 * Compare dataset with data stored in the file
	 *
	 * @param  string                                       $filename
	 * @param  PHPUnit_Extensions_Database_DataSet_IDataSet $expected
	 * @return boolean
	 */
	public function assertDataSetsMatchXML($filename, PHPUnit_Extensions_Database_DataSet_IDataSet $actual) {
		if (empty($filename) || !is_string($filename)) {
			throw new InvalidArgumentException('Second parameter "filename" is not a valid string.');
		}

		$expected = $this->createFlatXmlDataSet($this->getSeedFilesPath() . $filename);
		$expectedF = new PHPUnit_Extensions_Database_DataSet_DataSetFilter($expected, array('blog' => array('created')));

		return $this->assertDataSetsEqual($expectedF, $actual);
	}
}